package server.orders;

import java.io.IOException;
import java.sql.Date;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import json.JSONObjectWrapper;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import server.database.AbstractTable;
import server.database.DatabaseColumn;
import server.database.DatabaseService;
import server.database.query.IQueryResult;
import server.servlet.AbstractEntityServlet;
import utils.StringUtils;

import com.google.common.collect.Lists;

public class OrdersServlet extends AbstractEntityServlet
{
	private static final long serialVersionUID = -1980808148291282463L;

	public static final String PATH = API + "/orders";

	public static final String ORDER = "order";
	public static final String ORDERS = "orders";

	public static final String OPEN = "0";
	public static final String CLOSED = "1";
	public static final String IN_PROGRESS = "2";

	private static final String LINES_IN_ORDER = "lines_in_order";

	public static final String PENDING_DELIVERY = "0";
	public static final String DELIVERY_SCHEDULED = "1";
	public static final String DELIVERED = "2";
	public static final String RETURNED = "3";

	@Override
	protected String getEntityName()
	{
		return ORDER;
	}

	@Override
	protected String getEntitiesName()
	{
		return ORDERS;
	}

	@Override
	protected OrdersTable getTable()
	{
		return (OrdersTable) DatabaseService.getInstance().getTable(OrdersTable.TABLE_NAME);
	}

	private CustomersOrdersTable getCustomersOrdersTable()
	{
		return (CustomersOrdersTable) DatabaseService.getInstance().getTable(CustomersOrdersTable.TABLE_NAME);
	}

	private LineInOrderTable getLineInOrderTable()
	{
		return (LineInOrderTable) DatabaseService.getInstance().getTable(LineInOrderTable.TABLE_NAME);
	}

	@Override
	protected void doAddPost(JSONObjectWrapper request, JSONObject output) throws ServletException, IOException
	{
		JSONObjectWrapper entity = request.getJsonValue(getEntityName());

		Map<DatabaseColumn, String> mpValues = parseEntityValues(entity, getTable());
		Date current = new Date(System.currentTimeMillis());
		mpValues.put(OrdersTable.OPEN_DATE, String.valueOf(current));
		mpValues.put(OrdersTable.STATUS_DATE, String.valueOf(current));

		IQueryResult ordersResult = getTable().insert(mpValues);

		if (ordersResult.getResult() != IQueryResult.SUCESS)
		{
			setFail(output, UNEXPECTED_ERROR, ordersResult.getError());
			return;
		}

		int iOrderID = ordersResult.getAutoIncrementedValue();
		Map<DatabaseColumn, String> mpCustomerOrderValues = parseEntityValues(entity, getCustomersOrdersTable());
		mpCustomerOrderValues.put(CustomersOrdersTable.ORDER_ID, String.valueOf(iOrderID));

		IQueryResult customersOrdersResult = getCustomersOrdersTable().insert(mpCustomerOrderValues);

		if (customersOrdersResult.getResult() != IQueryResult.SUCESS)
		{
			setFail(output, UNEXPECTED_ERROR, customersOrdersResult.getError());
			return;
		}

		JSONArray linesInOrder = entity.getJsonArray(LINES_IN_ORDER);
		for (Object lineObject : linesInOrder)
		{
			JSONObjectWrapper line = new JSONObjectWrapper((JSONObject) lineObject);
			Map<DatabaseColumn, String> mpLineValues = parseEntityValues(line, getLineInOrderTable());
			mpLineValues.put(CustomersOrdersTable.ORDER_ID, String.valueOf(iOrderID));

			getLineInOrderTable().insert(mpLineValues);
			// TODO - need to remove all lines on failure
		}

		output.put(RESULT, true);
	}

	@Override
	protected void doGetSpecific(HttpServletRequest request, HttpServletResponse response, JSONObject output) throws ServletException, IOException
	{
		IQueryResult queryResult = null;

		List<DatabaseColumn> lstFields = Lists.newArrayList();
		List<String> lstValues = Lists.newArrayList();

		String sID = request.getParameter(getTable().ID.getName());
		if (StringUtils.isEmpty_DB(sID))
		{
			String sSalesmanID = request.getParameter(OrdersTable.SALESMAN_ID.getName());

			if (!StringUtils.isEmpty_DB(sSalesmanID))
			{
				lstFields.add(OrdersTable.SALESMAN_ID);
				lstValues.add(sSalesmanID);
			}
			queryResult = getTable().getAllEntities(lstFields, lstValues, AbstractTable.AND);
			output.put(QUERY_RESULT, queryResult.getResult());
		}
		else
		{
			queryResult = querySpecificID(request, lstFields, lstValues);
			output.put(QUERY_RESULT, queryResult.getResult());
		}

		if (queryResult.getResult() == IQueryResult.SUCESS)
		{
			output.put(RESULT, true);

			JSONArray orders = new JSONArray();
			buildEntityValues(queryResult.getResultValues(), orders, getTable());
			LineInOrderTable linesInOrderTable = getLineInOrderTable();

			for (Object orderObject : orders)
			{
				JSONObjectWrapper object = new JSONObjectWrapper((JSONObject) orderObject);
				String sOrderID = object.getStringValue(getTable().ID.getName());

				IQueryResult linesQuery = getLineInOrderTable().getAllEntities(Arrays.asList(LineInOrderTable.ORDER_ID), Arrays.asList(sOrderID), getTable().AND);
				if (linesQuery.getResult() == IQueryResult.SUCESS)
				{
					JSONArray lines = new JSONArray();
					buildEntityValues(linesQuery.getResultValues(), lines, getLineInOrderTable());
					object.putValue(LINES_IN_ORDER, lines);
				}
			}

			output.put(getEntitiesName(), orders);

		}
		else if (queryResult.getResult() != IQueryResult.NO_RESULTS)
		{
			setFail(output, UNEXPECTED_ERROR, UNEXPECTED_ERROR);
		}
		else
		{
			output.put(RESULT, false);
			output.put(QUERY_RESULT, IQueryResult.NO_RESULTS);
		}
	}

}
